package com.tju.backend.resources.config.security.configSecurity;

import com.tju.backend.resources.config.security.components.JwtTokenUtil;
import com.tju.backend.utils.redis.RedisService;
import com.tju.backend.utils.tool.Constants;
import com.tju.backend.utils.tool.EmptyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Service;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 拦截器
 *
 * @USER: CLS
 */
@Service
public class MyOncePerRequestFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RedisService redisService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //获取到前端携带的token
        String headerToken = request.getHeader(Constants.Authorization);
        if (EmptyUtils.isNotEmpty(headerToken)) {
            //postMan测试时，自动假如的前缀，要去掉。
            String token = headerToken.replace("Bearer", "").trim();
            //判断令牌是否过期
            boolean check = false;

            if (this.jwtTokenUtil.isTokenExpired(token, redisService)) {
                check = true;
            } else {
                new Throwable("令牌已过期，请重新登录。");
            }
            if (check) {
                //通过令牌获取用户名称
                String username = jwtTokenUtil.getUsernameFromToken(token);
                //判断用户不为空，且SecurityContextHolder授权信息还是空的
                if (EmptyUtils.isNotEmpty(username) && EmptyUtils.isEmpty(SecurityContextHolder.getContext().getAuthentication())) {
                    //通过用户信息得到UserDetails
                    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                    //验证令牌有效性
                    boolean validata = false;
                    if (jwtTokenUtil.validateToken(token, userDetails)) {
                        validata = true;
                    } else
                        new Throwable("验证token无效");
                    if (validata) {
                        // 将用户信息存入 authentication，方便后续校验
                        UsernamePasswordAuthenticationToken authentication =
                                new UsernamePasswordAuthenticationToken(
                                        userDetails,
                                        null,
                                        userDetails.getAuthorities()
                                );
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        // 将 authentication 存入 ThreadLocal，方便后续获取用户信息
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                }
            } else
                new Throwable("令牌已过期，请重新登录。");
        }
        chain.doFilter(request, response);
    }
}
